Process的使用

您所在的位置:网站首页 java process 进程交互 Process的使用

Process的使用

2023-06-03 02:03| 来源: 网络整理| 查看: 265

前言

目前需要做一个功能,就是通过java进行mysqldump备份,但是mysql时运行在容器中的时候, 已知Java目前只有一个Runtime.getRuntime()一种方式能获得当前linux运行时环境的方式 所以接下来就是通过这个方式实现这个功能

遇到的问题一:process.waitFor()一直阻塞不返回

代码: 下面是实现代码:

public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; // 回去结果 int exitCode=process.waitFor(); Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } if (exitCode != 0){ log.error("错误") } } }

原因:

process.waitFor()方法和exitValue()方法很像, 但是exitValue()是直接获得一个返回结果,但是有可能命令还在执行中,因此结果不一定正确; 而waitFor()方法是等待进程结束后才会有返回值。

因此waitfor方法是会被阻塞的,同时因为因为输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败,当缓冲区满之后将无法继续写入数据,则可能导致子进程阻塞

因此我们需要不断的将缓冲区的内容读取出来就了以防止阻塞,所以process.waitFor()应该换个位置

改进代码如下:

public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } // 回去结果 int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } } 遇到的问题二:process.waitFor()返回值为127

查明原因127对应的应该是没有环境导致的, 因此在使用Process 的过程中推荐使用绝对路径,就算docker也一样

代码改进如下:

public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ String cmdStr = "/usr/bin/docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } // 回去结果 int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } } 遇到的问题三:process.waitFor()返回值为1

返回值为1的原因大概是因为执行的语句有问题,但是我将该语句放到linux环境中执行却能过得到正常结果

后面简单的百度一下并且看了一下源码: 发现Runtime.exec()是存在两种字符参数的 分别是:

1、Runtime.exec(String command)2、Runtime.exec(String[] cmdarray)

但是第1种方法的本质是Runtime.exec(command.split(" ")) 看下代码,可以见到我们通过linux执行docker命令,在通过docker 执行容器命令,简单的空格已经不能支持这么复杂的逻辑了,其实一些包含特殊字符的也不能进行执行,所以我们需要使用第二种方式,手动将命令分层

改进代码如下:

public void backup(HttpServletResponse reponse){ BufferedReader reader; try{ //String cmdStr = " mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8"; //String cmdStr = "docker exec mysql sh -c 'mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8'"; String[] cmdStr = {"/usr/bin/docker","exec","mysql","sh","-c","/usr/bin/mysqldump -h 127.0.0.1 -uroot -p123456 database --ser-charset=UTF-8"} Process exec = Runtime.getRuntime.exec(cmdStr); reader=new BufferedReader(new InputStreamReader(process.getInputStream())); String line=null; while((line=reader.readLine())!=null){ System.out.println(line); } int exitCode=process.waitFor(); if (exitCode != 0){ log.error("错误") } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3